Add FromJSON instance for new experimental TxOut#1179
Conversation
87cfa8a to
bc2431f
Compare
bc2431f to
9734a72
Compare
|
This PR is stale because it has been open 45 days with no activity. |
4c0be1f to
3467b7f
Compare
Add per-era FromJSON instances for the experimental TxOut type, mirroring the ToJSON structure. Pre-Alonzo eras parse address and value only; Alonzo adds datum hash support; Babbage+ adds inline datum (parsed from inlineDatumRaw with hash validation) and reference script support. Supplemental datums are deliberately unsupported as the ledger TxOut does not carry them.
3467b7f to
223fb95
Compare
There was a problem hiding this comment.
Pull request overview
This PR adds FromJSON support for the experimental TxOut era wrapper (around L.TxOut era), intended to be the inverse of the ToJSON format introduced in #1176, and adds a property test to verify JSON round-tripping for supported Shelley-based eras.
Changes:
- Implement
FromJSONinstances for experimentalTxOutacross Shelley→Conway, including Babbage+ inline datum parsing (frominlineDatumRaw) with hash validation and reference script support. - Refactor datum/reference-script JSON field emission to a shared helper (
datumAndRefScriptFields). - Add a Hedgehog property test for
encode/eitherDecoderound-tripping, plus a Herald changelog fragment.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| cardano-api/test/cardano-api-test/Test/Cardano/Api/Json.hs | Adds a JSON round-trip property for the new experimental TxOut (with Dijkstra currently skipped). |
| cardano-api/src/Cardano/Api/Experimental/Tx/Internal/BodyContent/New.hs | Adds FromJSON parsing for experimental TxOut (base fields, datum hash, inline datum raw+hash validation, reference scripts). |
| .changes/20260420_cardano_api_fromjson_experimental_txout.yml | Adds the required changelog fragment documenting the new feature. |
| -- | Verify that the new experimental 'TxOut' round-trips through JSON | ||
| -- (encode then decode) for all Shelley-based eras. | ||
| prop_new_txout_json_roundtrip :: Property |
| Nothing -> case mDatumHash of | ||
| Just dh -> pure $ L.DatumHash dh | ||
| Nothing -> pure L.NoDatum |
palas
left a comment
There was a problem hiding this comment.
Looks good. I just made a couple of small suggestions.
inlineDatumhash is really weird, both the capitalisation and it being omitted on Babbage when it inline datum is not present (instad of just being null). But it is outside of the scope of the PR
There was a problem hiding this comment.
I think usage of cast is imprecise here and will be an annoyance down the road. I think we should stop for a moment and decide how we would like to support legacy eras using experimental API.
Moreover, PR has a lot of duplication from pattern matching on Maybe and Either.
| Add FromJSON instances for the new experimental TxOut type, matching | ||
| the JSON format produced by the corresponding ToJSON instances. Inline | ||
| datums are parsed from inlineDatumRaw with hash validation against | ||
| inlineDatumhash. Reference scripts are parsed via the existing | ||
| FromJSON ScriptInAnyLang instance and converted to ledger scripts. | ||
| Supplemental datums are deliberately unsupported since the ledger | ||
| TxOut does not carry them. |
There was a problem hiding this comment.
redundant line wraps - they will leak into the final changelog
| rawBytes <- case Base16.decode (Text.encodeUtf8 rawHex) of | ||
| Left err -> fail $ "babbageOnwardsTxOutParseJson: failed to hex-decode inlineDatumRaw: " <> show err | ||
| Right bs -> pure bs |
There was a problem hiding this comment.
The explicit case matching on Maybe and Either repeats itself too many times in this PR. I think this warrants creating helper functions to make the code more readable.
We have failEitherWith for example:
| rawBytes <- case Base16.decode (Text.encodeUtf8 rawHex) of | |
| Left err -> fail $ "babbageOnwardsTxOutParseJson: failed to hex-decode inlineDatumRaw: " <> show err | |
| Right bs -> pure bs | |
| rawBytes <- failEitherWith (("babbageOnwardsTxOutParseJson: failed to hex-decode inlineDatumRaw: " <>) . show) $ | |
| Base16.decode (Text.encodeUtf8 rawHex) |
| refScript <- case mRefScript of | ||
| Nothing -> pure SNothing | ||
| Just script -> SJust <$> scriptInAnyLangToLedgerScript script |
There was a problem hiding this comment.
| refScript <- case mRefScript of | |
| Nothing -> pure SNothing | |
| Just script -> SJust <$> scriptInAnyLangToLedgerScript script | |
| refScript <- fmap maybeToStrictMaybe $ forM mRefScript scriptInAnyLangToLedgerScript |
| & L.datumTxOutL .~ datum | ||
| & L.referenceScriptTxOutL .~ refScript | ||
|
|
||
| -- | Convert a 'ScriptInAnyLang' to a ledger 'L.Script'. Reverse of 'ledgerScriptToScriptInAnyLang'. |
There was a problem hiding this comment.
This function should be placed near its reverse.
Replace the three separate where-bound helpers (datumFields, inlineDatumFields, refScriptFields) with a single top-level datumAndRefScriptFields function. Simplifies alonzoOnwardsTxOutToJson and documents the per-era field layout in one place.
85485f6 to
e7109d8
Compare
Replace cast-based value dispatch with ShelleyBasedEra era dispatch, removing all uses of Data.Typeable.cast. Use failEitherWith for hex/CBOR decode errors, maybe for NoDatum/DatumHash, forM + maybeToStrictMaybe for reference script, and mconcat for the hash mismatch error message. Add multi-asset guard for pre-Mary eras. Move scriptInAnyLangToLedgerScript next to its reverse. Fix test Haddock and add inline note for Dijkstra skip.
e7109d8 to
abf58f2
Compare
Context
Implements
FromJSONinstances for the newTxOut eratype (which wrapsL.TxOut era) in the experimental API, matching the JSON format produced by theToJSONinstances added in #1176.Closes #926
Changelog
How to trust this PR
FromJSONinstances for each era (Shelley through Conway), mirroring theToJSONstructure from Add ToJSON instance for new experimental TxOut #1176txOutBaseParseJsonhelperdataHashTxOutLinlineDatumRaw(hex-encoded original CBOR bytes) with hash validation againstinlineDatumhash, and reference script parsing viascriptInAnyLangToLedgerScriptaddrFromJson(reverse ofaddrToJson),scriptInAnyLangToLedgerScript(reverse ofledgerScriptToScriptInAnyLang)fromJSON . toJSON = id) across all Shelley-based erasChecklist
fourmolu